/**输入框文字对齐方式 */
const AlignType = cc.Enum({
    左对齐: 0,
    居中: 1
});

cc.Class({
    extends: cc.Component,
    properties: {
        //在编辑器上提供预览效果的文本
        editorString: {
            displayName: "文本",
            default: "",
            editorOnly: true,
            notify: function notify() {
                this._textRef.string = this.editorString;
                if (this.editorString == "") {
                    this._placeHolderRef.node.active = true;
                    this._textRef.node.active = false;
                } else {
                    this._textRef.node.active = true;
                    this._placeHolderRef.node.active = false;
                }
            },
        },
        font: {
            displayName: "字体",
            type: cc.Font,
            default: null,
            notify: function notify() {
                if (this.node) {
                    this._placeHolderRef.font = this.font;
                    this._textRef.font = this.font;
                }
            }
        },
        color: {
            displayName: "字体颜色",
            default: new cc.Color(),
            notify: function notify() {
                this._textRef.node.color = this.color;
            }
        },
        fontSize: {
            displayName: "字体大小",
            default: 20,
            notify: function notify() {
                this._textRef.fontSize = this.fontSize;
                this._placeHolderRef.fontSize = this.fontSize;
            }
        },
        lineHeight: {
            displayName: "行高",
            default: 20,
            notify: function notify() {
                this._textRef.lineHeight = this.lineHeight;
                this._placeHolderRef.lineHeight = this.lineHeight;
            }
        },
        align: {
            displayName: "对齐",
            type: AlignType,
            default: AlignType.左对齐,
            notify(oldValue) {
                if (oldValue == this.align) {
                    return;
                }

                this._initLabelAlign();
            }
        },
        maxLength: {
            displayName: "最大字符长度",
            default: 20
        },
        placeholder: {
            displayName: "占位符",
            default: "输入文本...",
            notify: function notify() {
                this._placeHolderRef.string = this.placeholder;
            }
        },
        placeholderColor: {
            displayName: "占位符颜色",
            default: new cc.Color(),
            notify: function notify() {
                this._placeHolderRef.node.color = this.placeholderColor;
            }
        },
        onEditingStart: {
            displayName: "输入开始监听器",
            type: cc.Component.EventHandler,
            default: null
        },
        onTextChange: {
            displayName: "文字变更监听器",
            type: cc.Component.EventHandler,
            default: null
        },
        onEditingEnd: {
            displayName: "输入结束监听器",
            type: cc.Component.EventHandler,
            default: null
        },

        //获取输入框文本内容的接口
        string: {
            visible: false,
            get() {
                if (this._labelText) {
                    return this._labelText.string;
                } else {
                    return "";
                }
            },
            set(value) {
                this._labelText.string = value;
            }
        },
        //编辑器下获取文本标签的引用
        _textRef: {
            get: function get() {
                return this.node.getChildByName("Text").getComponent(cc.Label);
            },
            set: function set() { }
        },
        //编辑器下获取占位符文本的引用
        _placeHolderRef: {
            get: function get() {
                return this.node.getChildByName("PlaceHolder").getComponent(cc.Label);
            },
            set: function set() { }
        }
    },

    //开启在编辑器下运行脚本
    editor: {
        executeInEditMode: true
    },

    ctor() {
        //初始化回调函数的属性
        this.onEditingStart = new cc.Component.EventHandler();
        this.onTextChange = new cc.Component.EventHandler();
        this.onEditingEnd = new cc.Component.EventHandler();
        //一些节点的引用
        this._cursor = null;
        this._labelText = null;
        this._editBox = null;
        this._placeHolder = null;

        //标记当前是否处于编辑状态
        this._isEditing = false;
        //实现光标闪烁所需的计时器
        this._blinkTimer = 0;
    },

    onLoad() {
        //非编辑器环境下删除所有子节点，以便初始化输入框
        if (!CC_EDITOR) {
            this.node.removeAllChildren();
        }

        //创建带输入框组件的节点。弹出及收起键盘、获取输入的文字，都是通过这个组件来实现的
        let nodeEditBox = new cc.Node("EditBox");
        nodeEditBox.width = this.node.width;
        nodeEditBox.height = 0;
        var editBox = nodeEditBox.addComponent(cc.EditBox);
        this.node.addChild(nodeEditBox, 0);
        //默认单行输入
        editBox.inputMode = cc.EditBox.InputMode.SINGLE_LINE;
        editBox.maxLength = this.maxLength;
        //设置此项为true以便可以响应setFocus
        editBox.stayOnTop = true;
        this._editBox = editBox; 

        //创建文本显示节点。显示在输入框输入的文字，通过读取cc.EditBox组件的文字来更新自身文字内容
        var nodeText = this.node.getChildByName("Text");
        if (!nodeText) {
            nodeText = new cc.Node("Text");
            this.node.addChild(nodeText, 1);
            nodeText.active = false;
            var label = nodeText.addComponent(cc.Label);
            nodeText.color = this.color;
            label.fontSize = this.fontSize;
            label.lineHeight = this.lineHeight;
            if (this.font) {
                label.font = this.font;
            }
        }
        this._labelText = nodeText.getComponent(cc.Label);

        //创建占位符文本显示节点
        var nodePlaceholder = this.node.getChildByName("PlaceHolder");
        if (!nodePlaceholder) {
            nodePlaceholder = new cc.Node("PlaceHolder");
            this.node.addChild(nodePlaceholder, 2);
            var _label = nodePlaceholder.addComponent(cc.Label);
            _label.string = this.placeholder;
            nodePlaceholder.color = this.placeholderColor;
            if (this.font) {
                _label.font = this.font;
            }
            _label.lineHeight = this.lineHeight;
            _label.fontSize = this.fontSize;
        }
        this._placeHolder = nodePlaceholder;

        //初始化文本标签的对齐方式
        this._initLabelAlign();

        //创建光标
        //光标的实现方式是：本身是带cc.Label的节点，文本内容为一个特殊字符“█”，即是一个实心方块
        //然后设置节点宽度为1，设置文本显示会被节点宽度限制
        var cursor = this.node.getChildByName("Cursor");
        if (!cursor) {
            cursor = new cc.Node("Cursor");
            cursor.height = this.fontSize;
            cursor.color = this.color;
            cursor.active = false;
            this.node.addChild(cursor, 3);
            let label = cursor.addComponent(cc.Label);
            label.string = "█";
            //超出则截断，以便控制实色块宽度
            label.overflow = cc.Label.Overflow.CLAMP;
            label.lineHeight = this.lineHeight;
            cursor.width = 1;
            label.fontSize = this.fontSize;
            cursor.height = this.fontSize;
        }
        this._cursor = cursor;

        //设置触摸开始事件监听器，以便点击输入框开始输入文字
        this.node.on("touchend", () => {
            this._startEdit();
        });

        //监听cc.EditBox组件产生的事件，以实现变更输入文字，结束输入的操作
        //监听到事件后，调用在属性检查器上绑定的相应的回调函数
        this._editBox.node.on("editing-did-began", () => {
            if (this.onEditingStart.target
                && this.onEditingStart.component != ""
                && this.onEditingStart.handler != "") {
                this.onEditingStart.target.getComponent(this.onEditingStart.component)[this.onEditingStart.handler](this.onEditingStart.customEventData);
            }
        });
        this._editBox.node.on("text-changed", () => {
            this._labelText.string = this._editBox.string;
            if (this.onTextChange.target
                && this.onTextChange.component != ""
                && this.onTextChange.handler != "") {
                this.onTextChange.target.getComponent(this.onTextChange.component)[this.onTextChange.handler](this.onTextChange.customEventData);
            }
        });
        this._editBox.node.on("editing-did-ended", () => {
            this._isEditing = false;
            if (this.onEditingEnd.target
                && this.onEditingEnd.component != ""
                && this.onEditingEnd.handler != "") {
                this.onEditingEnd.target.getComponent(this.onEditingEnd.component)[this.onEditingEnd.handler](this.onEditingEnd.customEventData);
            }
        });
    },

    _initLabelAlign() {
        let setLabelAlign = (label, data) => {
            label.node.anchorX = data.anchorX;
            label.node.x = data.x;
        };

        let data = null;
        switch (this.align) {
            case AlignType.左对齐:
                data = {
                    anchorX: 0,
                    x: -this.node.width / 2
                };
                break;
            case AlignType.居中:
                data = {
                    anchorX: 0.5,
                    x: 0
                };
                break;
            default:
                console.error("invalid enum value");
                return;    //防止后面传参错误导致报错
        }
        setLabelAlign(this._textRef, data);
        setLabelAlign(this._placeHolderRef, data);
    },

    //每帧更新光标的状态
    update(dt) {
        if (!CC_EDITOR) {
            this._updateCursor(dt);
        }
    },

    //实现光标闪烁
    _updateCursor(dt) {
        if (!this._isEditing) {
            this._cursor.active = false;
            return;
        }
        let interval = Math.ceil(this.fontSize / 10);
        switch (this.align) {
            case AlignType.左对齐:
                this._cursor.x = this._labelText.node.x + this._labelText.node.width + this._cursor.width / 2 + interval;
                break;
            case AlignType.居中:
                this._cursor.x = this._labelText.node.x + this._labelText.node.width / 2 + this._cursor.width / 2 + interval;
            default:
                break;
        }

        if (this._blinkTimer >= 0.5) {
            this._blinkTimer = 0;
            this._cursor.active = !this._cursor.active;
        } else {
            this._blinkTimer += dt;
        }
    },

    _startEdit() {
        this._isEditing = true;
        this._editBox.setFocus();
        this._placeHolder.active = false;
        this._labelText.node.active = true;
        this._cursor.active = true;
        this._blinkTimer = 0;
    }
});